/*
Copyright 2007 Nathan Baker

This file is part of XAliens.

XAliens is free software: you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

XAliens is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public License
along with XAliens.  If not, see <http://www.gnu.org/licenses/>.
 */

package main;

import event.MainEventHandler;
import sprites.BackgroundScroller;
import sprites.PlayerShip;
import utils.BoundsRect;
import utils.SpriteMap;
import utils.StopWatch;
import utils.UserPrompt;

import javax.swing.*;
import java.awt.*;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.image.BufferStrategy;

public class frmMain extends javax.swing.JFrame implements MouseListener {

    private static final long serialVersionUID = -1250073609877466652L;
    private JPanel _mainPanel;
    private BufferStrategy _strategy;
    private BackgroundScroller _background;
    private Graphics2D _screen;
    private SpriteMap _map;

    // image paths
    private String _shotPaths[] = {"images/shots/shot_yellow_1.png",
            "images/shots/shot_yellow_2.png"};
    private String _playerPath = "images/player/default.png";
    private String backgroundPath = "images/backgrounds/oceano.gif";

    // used to determine maximum boundaries of sprites
    private BoundsRect _reducedBounds;

    // TODO: Find a better way to do this. Maybe get the info from mainPanel.
    private final int _xOffset = 4; // left and right sides
    private final int _ytOffset = 26; // top
    private final int _ybOffset = 4; // bottom

    private int _fireInterval = 200; // in milliseconds
    private boolean _fire = false;
    private boolean _canFire = false; // false between fire intervals

    private int _backgroundIncrement = 2;
    private int _shotIncrement = 7;

    private StopWatch _stopWatch = new StopWatch();

    private boolean _gameRunning = true;

    private PlayerShip _userShip;

    public frmMain() throws Exception {
        super();
        initGUI();

        loadGameResources();
        mainLoop();
    } // frmMain()

    private void draw() {
        //      _background.draw(_screen);
        _userShip.draw(_screen);
        _userShip.drawShots(_screen);
    } // draw()

    private void moveSprites() {
        Point p = MouseInfo.getPointerInfo().getLocation();
        int x = p.x - getX() - (_userShip.getWidth() / 2);
        int y = (p.y - getY()) - (_userShip.getHeight() / 2);
        _userShip.setLocation(x, y, true);
        //      _background.increment(_backgroundIncrement);
        //_userShip.moveShots(_shotIncrement);
        _userShip.moveShots();
    } // moveSprites()

    /**
     * Loads resources such as sprites, sounds, music
     *
     * @return 1 for success, 0 for failure
     */
    private int loadGameResources() throws Exception {
        _reducedBounds = new BoundsRect(_xOffset, _ytOffset, getWidth()
                - (_xOffset * 2), getHeight() - (_ytOffset + _ybOffset));
        _map = new SpriteMap();
//
//
//        _background = new BackgroundScroller(_map.getImage(backgroundPath,
//        _screen));
//        _background.setParentWidth(getWidth());
//        _background.setParentHeight(getHeight());
//        _background.imageLoaded();
//        UserPrompt.print("Sanity check: _background.imageLoaded() == " + _background.imageLoaded().toString());

        _userShip = new PlayerShip(_map.getImage(_playerPath, _screen), _reducedBounds, 0, _shotIncrement);
        _userShip.setLocation(0, 0, false);
        _userShip.addShotFrame(_map.getImage(_shotPaths[0], _screen));
        _userShip.addShotFrame(_map.getImage(_shotPaths[1], _screen));
        UserPrompt.print("Sanity check: _userShip.imageLoaded() == " + _userShip.imageLoaded().toString());
        _stopWatch.start();


        return 1;
    } // loadGameResources()

    private void initGUI() {
        try {
            // set up the main JPanel
            _mainPanel = new JPanel();
            FlowLayout mainPanelLayout = new FlowLayout();
            mainPanelLayout.setHgap(0);
            mainPanelLayout.setVgap(0);
            add(_mainPanel, BorderLayout.CENTER);
            _mainPanel.setLayout(mainPanelLayout);
            setTitle("Test Game.");
            setSize(800, 600);
            setIgnoreRepaint(true); // use accelerated graphics (don't let the
            // OS redraw my frame)
            setResizable(false);
            setVisible(true);

            // set up the buffer strategy (double buffering)
            createBufferStrategy(2);
            _strategy = getBufferStrategy();
            _screen = (Graphics2D) _strategy.getDrawGraphics();

            AlphaComposite alphaComposite = AlphaComposite
                    .getInstance(AlphaComposite.SRC_OVER);
            _screen.setComposite(alphaComposite);

            // set up the event listeners
            setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
            addMouseListener(this);
            addWindowListener(new MainEventHandler(this));
        } catch (Exception e) {
            e.printStackTrace();
        }
    } // initGUI()

    private void mainLoop() {
        while (_gameRunning) {

            // get the graphics surface and clear it off
            Graphics2D g = (Graphics2D) _strategy.getDrawGraphics();
            g.setColor(Color.black);
            g.fillRect(0, 0, 800, 600);

            moveSprites();
            draw();

            // check if user can fire
            long interval = _stopWatch.getElapsedTime();
            _canFire = (interval > _fireInterval);
            if (_fire && _canFire) {
                _userShip.fireShot();
                _canFire = false;
                _stopWatch.start();
            }

            _userShip.cleanupShots();

            _strategy.show();

            try {
                Thread.sleep(10);
            } catch (Exception e) {
            }

        }
    } // mainLoop()

    /*
      * (non-Javadoc)
      *
      * @see java.awt.event.MouseListener#mouseClicked(java.awt.event.MouseEvent)
      */
    public void mouseClicked(MouseEvent e) {

    }

    /*
      * (non-Javadoc)
      *
      * @see java.awt.event.MouseListener#mouseEntered(java.awt.event.MouseEvent)
      */
    public void mouseEntered(MouseEvent e) {

    }

    /*
      * (non-Javadoc)
      *
      * @see java.awt.event.MouseListener#mouseExited(java.awt.event.MouseEvent)
      */
    public void mouseExited(MouseEvent e) {
    }

    /*
      * (non-Javadoc)
      *
      * @see java.awt.event.MouseListener#mousePressed(java.awt.event.MouseEvent)
      */
    public void mousePressed(MouseEvent e) {
        _fire = true;
    }

    /*
      * (non-Javadoc)
      *
      * @see
      * java.awt.event.MouseListener#mouseReleased(java.awt.event.MouseEvent)
      */
    public void mouseReleased(MouseEvent e) {
        _fire = false;
    }
}